<style scoped lang="scss">
.entry-container {
  background-color: #fff;
  width: 100vw;
  height: 100vh;
  nav {
    display: flex;
    column-gap: 20px;
    padding-bottom: 10px;
    padding-left: 10px;
    border-bottom: 1px solid rgb(212, 209, 209);
    span {
      cursor: pointer;
      border: 1px solid transparent;
      padding: 5px 10px;
      border-radius: 5px;
      text-align: center;
      &.active {
        border: 1px solid rgb(212, 209, 209);
        color: var(--el-color-primary);
      }
    }
  }
  .current-msg-area {
    height: 500px;
    width: 100%;
    overflow-y: auto;
    padding: 20px;
    border-bottom: 1px solid rgb(212, 209, 209);
    box-sizing: border-box;
    pre {
      display: flex;
      column-gap: 20px;
      border-bottom: 1px solid rgb(212, 209, 209);
      padding: 10px;
      .info {
        display: flex;
        flex-direction: column;
        row-gap: 5px;
      }
      img {
        width: 200px;
        max-height: 100px;
      }
    }
  }
  .history-msg {
    padding: 20px;
    .search {
      display: flex;
      column-gap: 10px;
      > span {
        padding: 5px 10px;
        border-radius: 10px;
        border: 1px solid transparent;
        cursor: pointer;
        &.active {
          border: 1px solid rgb(212, 209, 209);
          color: var(--el-color-primary);
        }
      }
    }
    .total {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
  }
  .setting {
    padding: 20px;
    display: flex;
    flex-wrap: wrap;
    column-gap: 10px;
    row-gap: 10px;
    .item {
      width: 300px;
      display: flex;
      flex-direction: column;
      row-gap: 10px;
      border: 1px solid grey;
      border-radius: 10px;
      padding: 10px;
    }
  }
}
</style>
<template>
  <div class="entry-container">
    <nav>
      <span
        :class="{ active: currentTab === tab.value }"
        v-for="tab in tabs"
        @click="tabChange(tab)"
        >{{ tab.label }}</span
      >
    </nav>
    <main>
      <div v-if="currentTab === 0" class="current-msg-area">
        <pre v-for="(msg, index) in currentMsgList">
          <div class="info">
            <span style="color: brown;">{{ index+1 }}</span>
            <span>摄像头编号：{{ msg.deviceCode||'未知' }}</span>
            <span>捕捉的车牌号：{{ msg.plateNumber }}</span>
            <span>抓拍时间：{{ msg.captureTime }}</span>
          </div>
          <img :src="'data:image/jpeg;base64,'+msg.plateImage" alt="">
          <!-- <img src="../assets/ele.svg" alt=""> -->
        </pre>
      </div>
      <div class="history-msg" v-if="currentTab === 1">
        <div class="search">
          <el-button type="primary" @click="exportData">导出数据</el-button>
          <el-button type="danger" @click="delCurData">删除数据</el-button>
          <el-date-picker
            v-model="datePickValue"
            type="daterange"
            range-separator="To"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            :default-time="defaultTime"
            @change="dataPickChange"
            value-format="x"
            style="width: 200px"
          />
          <span
            :class="{ active: lastDaysOptions.curIndex === index }"
            v-for="(item, index) in lastDaysOptions.list"
            @click="lastDaysOptions.handleClick(index, item.days)"
            >{{ item.label }}</span
          >
        </div>
        <el-table :data="tableData" style="width: 100%; height: 400px">
          <el-table-column prop="composition1" label="摄像头1车牌" width="180" />
          <el-table-column prop="composition2" label="摄像头2车牌" width="180" />
          <el-table-column
            prop="isSame"
            label="是否相同"
            :formatter="
              (a, b, val) => {
                return val ? '是' : '否'
              }
            "
          />
          <el-table-column prop="captureTime" label="记录时间" />
        </el-table>
        <div class="total">
          <span>总计：{{ tableData.length }} 条</span>
          <span>相同合计：{{ sameCount }} 次</span>
          <span>不同合计：{{ diffCount }} 次</span>
        </div>
      </div>
      <div class="setting" v-if="currentTab === 2">
        <div class="item">
          <span>是否判断不同的设备车牌才记录</span>
          <el-select
            @change="isJudgeDeviceCodeChange"
            v-model="setting.isJudgeDeviceCode"
            placeholder="请选择"
            style="width: 240px"
          >
            <el-option
              v-for="item in setting.judgeList"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </div>
        <div class="item">
          <span>判定为一组车牌的时间间隔(单位/秒)</span>
          <el-input
            style="width: 240px"
            @change="judgeIntervalChange"
            v-model="setting.judgeInterval"
          />
        </div>
        <div class="item">
          <span>当前接收信息服务ip</span>
          <el-input style="width: 240px" v-model="setting.currentIp" /><el-button
            @click="restartService"
            type="primary"
            >重启</el-button
          >
        </div>
        <div class="item">
          <span>最大区别位数（车牌位差异小于该位数，才提示）</span>
          <el-input
            @change="maxDiffCountChange"
            style="width: 240px"
            v-model="setting.maxDiffCount"
          />
        </div>
        <div class="item">
          <span>警告弹窗倒计时关闭时间</span>
          <el-input @change="intervalChange" style="width: 240px" v-model="setting.timeInterval" />
        </div>
        <div class="item">
          <span>定期删除若干月之前的相同车牌数据（月）</span>
          <el-input @change="beforeDateChange" style="width: 240px" v-model="setting.beforeDate" />
        </div>
      </div>
    </main>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, nextTick, computed, onBeforeUnmount } from 'vue'
import msgHandler from '../utils/msg-saving'
import database from '../utils/indexDB'
import moment from 'moment'
import { ElMessage, ElMessageBox } from 'element-plus'
const scrollRef = ref()
const tabs = reactive([
  {
    label: '当前接收信息',
    value: 0
  },
  {
    label: '历史统计数据',
    value: 1
  },
  {
    label: '设置',
    value: 2
  }
])
// 重启服务
const restartService = () => {
  window.electron.ipcRenderer.send('restartServer', setting.currentIp)
  localStorage.setItem('localIp', setting.currentIp)
}
// 设置相关参数
const setting = reactive({
  isJudgeDeviceCode: localStorage.getItem('isJudgeDeviceCode') || '1', //是否判断不同的设备车牌才记录
  judgeInterval: Number(localStorage.getItem('judgeInterval') || 1.5) || 1.5, //当前判断时间间隔
  currentIp: '', // 当前服务IP地址
  maxDiffCount: localStorage.getItem('maxDiffCount') || 2,
  timeInterval: Number(localStorage.getItem('timeInterval') || 10) || 10, // 警告弹窗倒计时关闭时间
  beforeDate: Number(localStorage.getItem('beforeDate') || 1) || 1, // 定期删除若干月之前的数据
  judgeList: [
    {
      label: '是',
      value: '1'
    },
    {
      label: '否',
      value: '2'
    }
  ]
})
// 设置删除多久之前的数据
const beforeDateChange = () => {
  localStorage.setItem('beforeDate', setting.beforeDate)
}
// 弹窗倒计时更改
const intervalChange = () => {
  localStorage.setItem('timeInterval', setting.timeInterval)
}
// 判断是否判断不同设备车牌参数改变
const isJudgeDeviceCodeChange = () => {
  localStorage.setItem('isJudgeDeviceCode', setting.isJudgeDeviceCode)
}
// 判断时间间隔参数改变
const judgeIntervalChange = () => {
  localStorage.setItem('judgeInterval', setting.judgeInterval)
}
// 提示时的差异位数最大值
const maxDiffCountChange = () => {
  localStorage.setItem('maxDiffCount', setting.maxDiffCount)
}
// 表格数据
const tableData = ref([])
// 识别相同次数
const sameCount = computed(() => {
  return tableData.value.filter((item) => item.isSame).length
})
// 识别不同次数
const diffCount = computed(() => {
  return tableData.value.filter((item) => !item.isSame).length
})
// 当前tab切换选中
const currentTab = ref(0)
const tabChange = (tab) => {
  currentTab.value = tab.value
  // 切换tab更新数据
  datePickValue.value = ''
  lastDaysOptions.curIndex = -1
  getLocalData()
}
// 当前消息列表
const currentMsgList = ref([])
// 当前选中的日期
const datePickValue = ref('')
// 默认时间点设定
const defaultTime = ref([new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)])
const lastDaysOptions = reactive({
  curIndex: -1, //当前选中的显示时间按钮下标
  list: [
    {
      label: '最近一天',
      days: 1
    },
    {
      label: '最近一周',
      days: 7
    },
    {
      label: '最近一月',
      days: 30
    },
    {
      label: '最近一年',
      days: 365
    }
  ],
  // 点击时间按钮下标
  handleClick(index, days) {
    // 清空日期选择器选中
    datePickValue.value = ''
    // 可以取消按钮选中
    if (index != lastDaysOptions.curIndex) {
      lastDaysOptions.curIndex = index
      getLastDaysData(days)
    } else {
      lastDaysOptions.curIndex = -1
      getLocalData()
    }
  }
})
// 日期选择改变,转换日期为时间戳，获取对应范围的数据
const dataPickChange = (value) => {
  lastDaysOptions.curIndex = -1
  if (value) {
    getRangeData(value[0], value[1])
  } else {
    getLocalData()
  }
}

// 获取所有记录
const getLocalData = async () => {
  if (database.isConnected) {
    database.getAllData().then((r) => {
      if (r.length > 0) {
        r.forEach((item) => {
          item.captureTime = moment(item.timestamp).format('YYYY-MM-DD HH:mm:ss')
        })
        tableData.value = r.reverse()
      } else {
        tableData.value = []
      }
    })
    return
  }
  requestAnimationFrame(getLocalData)
}
// 获取最近若干天的数据
const getLastDaysData = (days) => {
  if (database.isConnected) {
    database.getRangeData(null, null, days).then((r) => {
      if (r.length > 0) {
        r.forEach((item) => {
          item.captureTime = moment(item.timestamp).format('YYYY-MM-DD HH:mm:ss')
        })
        tableData.value = r.reverse()
      } else {
        tableData.value = []
      }
    })
  }
}
// 获取某个时间段的数据
const getRangeData = (start, end) => {
  if (start && end) {
    database.getRangeData(start, end).then((r) => {
      if (r.length > 0) {
        r.forEach((item) => {
          item.captureTime = moment(item.timestamp).format('YYYY-MM-DD HH:mm:ss')
        })
        tableData.value = r.reverse()
      } else {
        tableData.value = []
      }
    })
  }
}
// 删除某个月之前的，相同判别数据
const deleteBeforeDateData = () => {
  if (database.isConnected) {
    // 获取当前时间戳
    const now = new Date()
    // 计算某个月前的时间戳
    let beforeDate = Number(localStorage.getItem('beforeDate') || 1) || 1
    const monthAgo = new Date()
    monthAgo.setMonth(now.getMonth() - beforeDate)
    // 判别相同,则删除该数据
    database
      .deleteBeforeDateData(monthAgo.getTime(), (data) => Boolean(data.isSame))
      .then(() => {
        console.log('删除成功')
      })
      .catch(() => {
        console.log('删除失败')
      })
    return true
  } else {
    return false
  }
}
let timerWatch = null
// 开启时间监听，删除某个月之前的相同数据
const openWatchTime = () => {
  // 确保首次调用成功，使用动画帧
  if (deleteBeforeDateData()) {
    timerWatch = setInterval(() => {
      deleteBeforeDateData()
    }, 1000 * 60)
  } else {
    requestAnimationFrame(openWatchTime)
  }
}
// 删除当前筛选出的数据
const delCurData = async () => {
  let tip = ''
  let isSuccess = false
  let whichList = 1
  if (datePickValue.value) {
    tip = '是否删除选中的时间段数据？'
    isSuccess = await ElMessageBox.confirm(tip, '提示').then(() => {
      return database.deleteRangeData(datePickValue.value[0], datePickValue.value[1]).then(
        () => true,
        () => false
      )
    })
    whichList = 2
  } else if (lastDaysOptions.curIndex != -1) {
    tip = `是否删除${lastDaysOptions.list[lastDaysOptions.curIndex].label}的数据？`
    isSuccess = await ElMessageBox.confirm(tip, '提示').then(() => {
      return database
        .deleteRangeData(null, null, lastDaysOptions.list[lastDaysOptions.curIndex].days)
        .then(
          () => true,
          () => false
        )
    })
    whichList = 3
  } else {
    tip = '是否删除所有数据？'
    isSuccess = await ElMessageBox.confirm(tip, '提示').then(() => {
      return database.deleteAllData().then(
        () => true,
        () => false
      )
    })
  }
  if (isSuccess) {
    ElMessage.success('删除成功')
    switch (whichList) {
      case 1:
        getLocalData()
        break
      case 2:
        getRangeData(datePickValue.value[0], datePickValue.value[1])
        break
      case 3:
        getLastDaysData(lastDaysOptions.list[lastDaysOptions.curIndex].days)
        break
    }
  } else {
    ElMessage.error('删除失败')
  }
}
// 导出当前筛选的菜单
const exportData = () => {
  let range = datePickValue.value
    ? datePickValue.value.map((item) => moment(item).format('YYYY-MM-DD')).join('至')
    : null
  let filename = range
    ? range
    : lastDaysOptions.curIndex == -1
      ? '全部识别数据'
      : lastDaysOptions.list[lastDaysOptions.curIndex].label + '识别数据'
  let curData = {
    sheets: [
      // 消息列表sheet
      {
        sheetHeader: [
          {
            header: '摄像头1车牌',
            key: 'composition1',
            width: '25'
          },
          {
            header: '摄像头2车牌',
            key: 'composition2',
            width: '25'
          },
          {
            header: '是否相同',
            key: 'isSame',
            width: '25'
          },
          // {
          //   header: '摄像头1车牌图片',
          //   key: 'plateDatabase1',
          //   width: '50'
          // },
          // {
          //   header: '摄像头2车牌图片',
          //   key: 'plateDatabase2',
          //   width: '50'
          // },
          {
            header: '记录时间',
            key: 'captureTime',
            width: '50'
          }
        ],
        sheetName: '消息列表',
        sheetData: tableData.value.map((item) => {
          let temp = {
            ...item,
            isSame: item.isSame ? '是' : '否'
          }
          delete temp.timestamp
          return temp
        })
      },
      // 统计数量sheet
      {
        sheetName: '识别次数',
        sheetHeader: [
          {
            header: '识别相同次数',
            key: 'sameCount',
            width: '15'
          },
          {
            header: '识别不同次数',
            key: 'diffCount',
            width: '15'
          }
        ],
        sheetData: [
          {
            sameCount: sameCount.value,
            diffCount: diffCount.value
          }
        ]
      }
    ],
    filename
  }
  window.electron.ipcRenderer.send('exportExcel', curData)
}
const init = () => {
  // 接受摄像头信息
  window.$bus.on('camera', (value) => {
    console.log('接收到摄像头数据：', value)
    if (currentMsgList.value.length > 20) {
      currentMsgList.value.splice(currentMsgList.value.length - 1, 1)
    }
    currentMsgList.value.unshift(value.params)

    // 处理信息并保存到本地数据库
    msgHandler.saveMsg(value)
    // nextTick(() => {
    //   scrollRef.value.scrollTo({
    //     top: scrollRef.value.scrollHeight,
    //     behavior: 'smooth'
    //   })
    // })
  })
  // 获取本地服务ip地址
  window.electron.ipcRenderer.send('getIp')
  window.$bus.on('local-ip', (data) => {
    setting.currentIp = data
    let cacheIp = localStorage.getItem('localIp')
    if (cacheIp) {
      setting.currentIp = cacheIp
      window.electron.ipcRenderer.send('restartServer', cacheIp)
    }
  })
  window.$bus.on('serverHasRestart', () => {
    ElMessage.success('重启成功')
  })
  // 导出文件结果
  window.$bus.on('export-result', (isSuccess) => {
    ElMessage[isSuccess ? 'success' : 'error'](isSuccess ? '导出成功' : '导出失败')
  })
}
init()
onMounted(() => {
  scrollRef.value = document.querySelector('.entry-container .current-msg-area')
  // openWatchTime()
  getLocalData()
})

onBeforeUnmount(() => {
  clearInterval(timerWatch)
})
</script>
